
    <!DOCTYPE html>
    <html lang="zh-CN">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Oracle练习题 - 学习卡片</title>
      <style>
        body { font-family: sans-serif; background-color: #f0f8ff; color: #333; display: flex; flex-direction: column; align-items: center; padding: 50px 20px; }
        .header h1 { font-size: 32px; }
        .grid-container { display: grid; grid-template-columns: repeat(3, 1fr); gap: 28px; width: 100%; max-width: 1200px; }
        .card-container { perspective: 1200px; cursor: pointer; height: 250px; }
        .card { width: 100%; height: 100%; position: relative; transform-style: preserve-3d; transition: transform 0.7s; border-radius: 16px; box-shadow: 0 4px 16px rgba(0,0,0,0.08); }
        .card-container.flipped .card { transform: rotateY(180deg); }
        .card-face { position: absolute; width: 100%; height: 100%; backface-visibility: hidden; display: flex; flex-direction: column; box-sizing: border-box; border-radius: 16px; background-color: #fff; padding: 24px; }
        .card-back { background-color: #f0fff4; transform: rotateY(180deg); justify-content: space-between; }
        .card-category { font-size: 14px; color: #0052d9; margin-bottom: 8px; font-weight: 500; }
        .card-question { font-size: 20px; font-weight: 500; flex-grow: 1; display: flex; align-items: center; justify-content: center; text-align: center; }
        .card-answer-wrapper { flex-grow: 1; overflow-y: auto; }
        .card-answer { font-size: 15px; line-height: 1.7; }
        .card-footer { font-size: 13px; color: #8a919f; border-top: 1px solid #f0f0f0; padding-top: 16px; margin-top: 16px; }
        .card-source { font-size: 13px; color: #8a919f; border-top: 1px solid #f0f0f0; padding-top: 12px; margin-top: 12px; }
      </style>
    </head>
    <body>
      <div class="header">
        <h1>Oracle练习题 - 学习卡片</h1>
      </div>
      <div class="grid-container">
        
    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">函数应用</div>
          <div class="card-question">在 SQL 中，如何计算员工的总收入（工资 + 奖金），并确保即使奖金（COMM）为 NULL 时也能正确求和？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">函数应用</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">使用 `nvl(e.comm, 0)` 函数，当 `e.comm` 为空时，会将其替换为 0 再进行加法运算。查询语句为：`select e.ename,e.sal+nvl(e.comm,0) sum from emp e`。</div>
          </div>
          <div class="card-source">来源: 文档中「（8）查询所有员工工资和奖金的和」部分</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">函数应用</div>
          <div class="card-question">如何使用 SQL 函数查询那些在每个月倒数第三天入职的员工信息？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">函数应用</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">可以使用 `last_day()` 函数获取月份的最后一天，然后减去2天，并与员工的入职日期（hiredate）进行比较。查询语句为：`select * from emp e where last_day(e.hiredate)-2 = e.hiredate;`。</div>
          </div>
          <div class="card-source">来源: 文档中「（10）查询各月倒数第3天入职的员工信息」部分</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">查询技巧</div>
          <div class="card-question">如何对查询结果进行多条件排序，例如先按工种（job）降序排列，如果工种相同，再按工资（sal）升序排列？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">查询技巧</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">在 `ORDER BY` 子句中指定多个列，并为每个列分别设置排序方向（`desc` 或 `asc`）。查询语句为：`select ename,job,sal,comm from emp order by job desc,sal asc`。</div>
          </div>
          <div class="card-source">来源: 文档中「（19）显示所有的姓名、工种、工资和奖金，按工种降序排列，若工种相同则按工资升序排列」部分</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">连接查询</div>
          <div class="card-question">如何通过一次查询，同时获取员工的姓名及其直接上级的姓名？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">连接查询</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">使用自连接（self-join），将 `emp` 表连接自身。通过条件 `a.mgr = b.empno`，将员工表 `a` 中的管理者ID（mgr）与管理者表 `b` 中的员工ID（empno）进行匹配。查询语句为：`select a.ename,b.ename from emp a,emp b where a.mgr = b.empno`。</div>
          </div>
          <div class="card-source">来源: 文档中「（25）查询所有员工的姓名及其直接上级的姓名」部分</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">连接查询</div>
          <div class="card-question">如何查询所有部门及其员工的信息，并且要确保即使某个部门没有任何员工，该部门的信息也会被显示出来？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">连接查询</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">使用外连接（OUTER JOIN）。在Oracle的旧式语法中，可以在作为次表的连接条件后添加 `(+)` 符号。例如在 `d.deptno = e.deptno(+)` 中，`dept` 表是主表，即使 `emp` 表中没有匹配项，`dept` 的记录也会显示。</div>
          </div>
          <div class="card-source">来源: 文档中「（27）查询所有部门及其员工信息，包括那些没有员工的部门」部分</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">分组与聚合</div>
          <div class="card-question">如何查询出最低工资大于2500的工种（job）有哪些？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">分组与聚合</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">首先按工种（job）进行 `GROUP BY` 分组，然后使用 `HAVING` 子句对分组后的结果进行筛选，条件是最低工资 `min(sal)` 大于2500。查询语句为：`select min(sal),job from emp group by job having min(sal) > 2500`。</div>
          </div>
          <div class="card-source">来源: 文档中「（30）查询最低工资大于2500的各种工作」部分</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">子查询</div>
          <div class="card-question">如何查询出工资高于公司平均工资的所有员工信息？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">子查询</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">使用子查询先计算出公司的平均工资 `(select avg(sal) from emp)`，然后在外层查询的 `WHERE` 子句中，筛选出工资（sal）大于这个平均值的员工。</div>
          </div>
          <div class="card-source">来源: 文档中「（33）查询工资高于公司平均工资的所有员工信息」部分</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">子查询</div>
          <div class="card-question">如何查询工资高于其*所在部门*平均工资的员工信息？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">子查询</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">首先通过子查询（或派生表）按部门 `group by deptno` 计算出每个部门的平均工资。然后将员工表与这个结果集进行连接，筛选出员工工资大于其对应部门平均工资的记录。查询语句为：`select e.* from emp e ,(select round(avg(sal)) sal,deptno from emp group by deptno)aa where e.sal > aa.sal and e.deptno = aa.deptno`。</div>
          </div>
          <div class="card-source">来源: 文档中「（45）查询工资高于本部门平均工资的员工的信息」部分</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">子查询</div>
          <div class="card-question">如何查询出那些在人数大于5的部门中工作的所有员工的信息？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">子查询</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">使用 `IN` 关键字配合子查询。子查询先按部门分组（`group by deptno`），然后用 `HAVING count(*) > 5` 筛选出人数大于5的部门编号（deptno）。外层查询则筛选出部门编号在子查询结果集中的所有员工。</div>
          </div>
          <div class="card-source">来源: 文档中「（51）查询部门人数大于5的部门的员工的信息」部分</div>
        </div>
      </div>
    </div>

      </div>
    </body>
    </html>
